package com.quick.scan.view;

import java.io.IOException;
import java.util.Vector;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.quick.scan.R;
import com.quick.scan.camera.CameraManager;
import com.quick.scan.camera.FlashlightManager;
import com.quick.scan.decoding.CaptureActivityHandler;
import com.quick.scan.decoding.InactivityTimer;
import com.quick.scan.impl.OnResultListerner;
import com.quick.scan.impl.ScanListener;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
import android.widget.FrameLayout;
import android.widget.Toast;

public class ZXingView extends FrameLayout implements Callback, ScanListener {
	private static final int PARSE_BARCODE_SUC = 300;
	private static final int PARSE_BARCODE_FAIL = 303;
	private static final long VIBRATE_DURATION = 200L;
	private static final float BEEP_VOLUME = 0.10f;

	private SurfaceView surfaceView;
	private ViewfinderView viewfinderView;
	private Activity mContext;
	private CaptureActivityHandler handler;
	private boolean hasSurface;
	private Vector<BarcodeFormat> decodeFormats;
	private String characterSet;
	private InactivityTimer inactivityTimer;
	private MediaPlayer mediaPlayer;
	private boolean playBeep;
	private boolean vibrate;
	private OnResultListerner listener;

	public ZXingView(Context context) {
		super(context);
		init(context);
	}

	public ZXingView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public ZXingView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	private void init(Context context) {
		mContext = (Activity) context;
		initViews(mContext);
		CameraManager.init(mContext.getApplication());
		hasSurface = false;
		inactivityTimer = new InactivityTimer(mContext);
	}

	private void initViews(Activity context) {
		surfaceView = new SurfaceView(context);
		FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
				LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
		params.gravity = Gravity.CENTER;
		addView(surfaceView, params);
		viewfinderView = new ViewfinderView(context, null);
		params = new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
				LayoutParams.MATCH_PARENT);
		addView(viewfinderView, params);
	}

	@SuppressLint("HandlerLeak")
	private Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch (msg.what) {
			case PARSE_BARCODE_SUC:
				if (listener != null) {
					listener.onResult((String) msg.obj);
				}
				break;
			case PARSE_BARCODE_FAIL:
				Toast.makeText(mContext, (String) msg.obj, Toast.LENGTH_LONG)
						.show();
				break;
			}
		}
	};

	/**
	 * 自动切换闪光灯
	 */
	public void toggleFlashLight() {
		CameraManager.get().toggleFlash();
	}

	public void onResume() {
		SurfaceHolder surfaceHolder = surfaceView.getHolder();
		if (hasSurface) {
			initCamera(surfaceHolder);
		} else {
			surfaceHolder.addCallback(this);
			surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
		}
		decodeFormats = null;
		characterSet = null;
		playBeep = true;
		AudioManager audioService = (AudioManager) mContext
				.getSystemService(Context.AUDIO_SERVICE);
		if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
			playBeep = false;
		}
		initBeepSound();
		vibrate = true;

	}

	public void onPause() {
		if (handler != null) {
			handler.quitSynchronously();
			handler = null;
		}
		CameraManager.get().closeDriver();
	}

	public void onDestroy() {
		inactivityTimer.shutdown();
	}

	public void setOnResultListerner(OnResultListerner l) {
		listener = l;
	}

	/** 处理解码信息 */
	public void handleDecode(Result result, Bitmap barcode) {
		inactivityTimer.onActivity();
		playBeepSoundAndVibrate();
		if (listener != null) {
			listener.onResult(result.getText());
		}
	}

	/** 初始化相机 */
	private void initCamera(SurfaceHolder surfaceHolder) {
		try {
			CameraManager.get().openDriver(surfaceHolder);
		} catch (IOException ioe) {
			return;
		} catch (RuntimeException e) {
			return;
		}
		if (handler == null) {
			handler = new CaptureActivityHandler(this, decodeFormats,
					characterSet);
		}
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (!hasSurface) {
			hasSurface = true;
			initCamera(holder);
		}
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		hasSurface = false;
	}

	@Override
	public ViewfinderView getViewfinderView() {
		return viewfinderView;
	}

	@Override
	public Handler getHandler() {
		return handler;
	}

	@Override
	public void drawViewfinder() {
		if (viewfinderView != null) {
			viewfinderView.drawViewfinder();
		}
	}

	/** 初始化提示音 */
	private void initBeepSound() {
		if (playBeep && mediaPlayer == null) {
			mContext.setVolumeControlStream(AudioManager.STREAM_MUSIC);
			mediaPlayer = new MediaPlayer();
			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
			mediaPlayer.setOnCompletionListener(beepListener);
			AssetFileDescriptor file = getResources().openRawResourceFd(
					R.raw.beep);
			try {
				mediaPlayer.setDataSource(file.getFileDescriptor(),
						file.getStartOffset(), file.getLength());
				file.close();
				mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
				mediaPlayer.prepare();
			} catch (IOException e) {
				mediaPlayer = null;
			}
		}
	}

	/** 播放提示音并震动 */
	private void playBeepSoundAndVibrate() {
		if (playBeep && mediaPlayer != null) {
			mediaPlayer.start();
		}
		if (vibrate) {
			Vibrator vibrator = (Vibrator) mContext
					.getSystemService(Context.VIBRATOR_SERVICE);
			vibrator.vibrate(VIBRATE_DURATION);
		}
	}

	/**
	 * 音频播放完成的回调
	 */
	private final OnCompletionListener beepListener = new OnCompletionListener() {
		public void onCompletion(MediaPlayer mediaPlayer) {
			mediaPlayer.seekTo(0);
		}
	};

	@Override
	public void setResult(int value, Intent intent) {
		if (mContext != null) {
			mContext.setResult(value, intent);
		}
	}

	@Override
	public void finish() {
		if (mContext != null) {
			mContext.finish();
		}
	}

	@Override
	public void startActivity(Intent intent) {
		if (mContext != null) {
			mContext.startActivity(intent);
		}
	}

}
